home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / FTPSUBR.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-23  |  6.8 KB  |  317 lines

  1. /* Routines common to both the FTP client and server
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  */
  4. /* Mods by G1EMM */
  5. /* Mods by KO4KS */
  6. #include "global.h"
  7. #include "mbuf.h"
  8. #include "socket.h"
  9. #include "ftp.h"
  10. #include "ftpcli.h"
  11. #include "usock.h"
  12. #include "md5.h"
  13.  
  14.  
  15. #if !defined(_lint)
  16. static char rcsid[] OPTIONAL = "$Id: ftpsubr.c,v 1.12 1996/12/23 22:44:37 root Exp root $";
  17. #endif
  18.  
  19. #define    MD5BLOCK    64    /* Preferred MD5 block size */
  20.  
  21. int md5hash (FILE * fp, char hash[16], int ascii);
  22. static void hashit (int hash, long total, long *hmark, int sent);
  23.  
  24.  
  25. static void
  26. hashit (hash, total, hmark, sent)
  27. int hash;
  28. long total, *hmark;
  29. int sent;
  30. {
  31.     while (hash && total >= (*hmark) + 1000) {
  32.         if (hash == V_HASH)
  33.             tputc ('#');
  34.         if (hash == V_BYTE)
  35.             tprintf ("Bytes %s : %ld\r", (sent) ? "sent" : "received", total);
  36.         *hmark += 1000;
  37.     }
  38.  
  39. }
  40.  
  41.  
  42. /* Send a file (opened by caller) on a network socket.
  43.  * Normal return: count of bytes sent
  44.  * Error return: -1
  45.  * re-written by KO4KS to (1) reduce code size (2) all binary compression
  46.  */
  47. long
  48. sendfile (fp, s, mode, hash)
  49. register FILE *fp;        /* File to be sent */
  50. register int s;            /* Socket to be sent on */
  51. int mode;            /* Transfer mode */
  52. int hash;            /* Print hash marks every BLKSIZE bytes */
  53. {
  54. register int c;
  55. register long total = 0;
  56. long hmark = 0;
  57. int oldf = 0;
  58. struct usock *up;
  59. register struct mbuf *bp;
  60.  
  61.     if (mode == ASCII_TYPE) {
  62.         oldf = setflush (s, -1);
  63.         /* Let the newline mapping code in usputc() do the work */
  64.         (void) sockmode (s, SOCK_ASCII);
  65.     } else
  66.         (void) sockmode (s, SOCK_BINARY);
  67.     up = itop (s);
  68.     if (mode != ASCII_TYPE && up->zout == NULLLZW) {    /* also, not lzw compressed */
  69.         for (;;) {
  70.             kwait (0);    /* be a good neighbor and share! */
  71.             bp = ambufw (BLKSIZE);
  72.             if ((bp->cnt = (int16) fread (bp->data, 1, BLKSIZE, fp)) == 0) {
  73.                 free_p (bp);
  74.                 break;
  75.             }
  76.             kwait (0);    /* be a good neighbor and share! */
  77.             total += bp->cnt;
  78.             if (send_mbuf (s, bp, 0, NULLCHAR, 0) == -1) {
  79.                 total = -1;
  80.                 break;
  81.             }
  82.             hashit (hash, total, &hmark, 1);
  83.         }
  84.     } else {
  85.  
  86.         /* At this point, it is either ASCII_TYPE, or LZW compressed */
  87.         while ((c = getc (fp)) != EOF) {
  88.             if (mode == ASCII_TYPE) {
  89. #ifndef TNOS_68K
  90. #if !defined(UNIX) && !defined(__TURBOC__)
  91.                 if (c == '\r') {
  92.                     /* Needed only if the OS uses a CR/LF
  93.                      * convention and getc doesn't do
  94.                      * an automatic translation
  95.                      */
  96.                     continue;
  97.                 }
  98. #endif
  99. #else
  100.                 if (c == '\l')
  101.                     continue;
  102. #endif
  103.                 if (!c)
  104.                     continue;
  105.             }
  106.             if (usputc (s, uchar (c)) == -1) {
  107.                 total = -1;
  108.                 break;
  109.             }
  110.             total++;
  111.             hashit (hash, total, &hmark, 1);
  112.             if (!(total % 256))
  113.                 kwait (0);    /* be a good neighbor and share! */
  114.         }
  115.     }
  116.     if (mode == ASCII_TYPE) {
  117.         usflush (s);
  118.         (void) setflush (s, oldf);
  119.     }
  120.     if (hash)
  121.         tputc ('\n');
  122.     return total;
  123. }
  124.  
  125.  
  126. /* Receive a file (opened by caller) from a network socket.
  127.  * Normal return: count of bytes received
  128.  * Error return: -1
  129.  * re-written by KO4KS to (1) reduce code size (2) all binary compression
  130.  */
  131. long
  132. recvfile (fp, s, mode, hash)
  133. register FILE *fp;
  134. register int s;
  135. int mode;
  136. int hash;
  137. {
  138. register int c;
  139. register long total = 0;
  140. long hmark = 0;
  141. int cnt;
  142. struct usock *up;
  143. struct mbuf *bp;
  144.  
  145.     if (mode == ASCII_TYPE)
  146.         (void) sockmode (s, SOCK_ASCII);
  147.     else
  148.         (void) sockmode (s, SOCK_BINARY);
  149.     up = itop (s);
  150.     if (mode != ASCII_TYPE && up->zout == NULLLZW) {    /* also, not lzw compressed */
  151.         while ((cnt = recv_mbuf (s, &bp, 0, NULLCHAR, 0)) != 0) {
  152.             kwait (0);    /* be a good neighbor and share! */
  153.             if (cnt == -1) {
  154.                 total = -1;
  155.                 break;
  156.             }
  157.             total += cnt;
  158.             hashit (hash, total, &hmark, 0);
  159.             kwait (0);    /* be a good neighbor and share! */
  160.             if (fp != NULLFILE) {
  161.                 if (write_p (fp, bp) == -1) {
  162.                     free_p (bp);
  163.                     total = -1;
  164.                     break;
  165.                 }
  166.                 free_p (bp);
  167.             } else
  168.                 (void) send_mbuf (Curproc->output, bp, 0, NULLCHAR, 0);
  169.             kwait (0);    /* be a good neighbor and share! */
  170.         }
  171.     } else {
  172.         while ((c = recvchar (s)) != EOF) {
  173.             if (fp != NULLFILE) {
  174. #if !defined(UNIX) && !defined(__TURBOC__)
  175.                 if (mode == ASCII_TYPE) {
  176.                     if (c == '\n') {
  177.                         /* Needed only if the OS uses a CR/LF
  178.                          * convention and putc doesn't do
  179.                          * an automatic translation
  180.                          */
  181.                         (void) putc ('\r', fp);
  182.                     }
  183.                 }
  184. #endif
  185.                 if (putc (c, fp) == EOF) {
  186.                     total = -1;
  187.                     break;
  188.                 }
  189.             } else
  190.                 tputc (uchar (c));
  191.             total++;
  192.             hashit (hash, total, &hmark, 0);
  193.             if (!(total % 256))
  194.                 kwait (0);    /* be a good neighbor and share! */
  195.         }
  196.     }
  197.     /* Detect an abnormal close */
  198.     if (socklen (s, 0) == -1)
  199.         total = -1;
  200.     if (hash)
  201.         tputc ('\n');
  202.     return total;
  203. }
  204.  
  205.  
  206. /* Determine if a file appears to be binary (i.e., non-text).
  207.  * Return 1 if binary, 0 if ascii text after rewinding the file pointer.
  208.  *
  209.  * Used by FTP to warn users when transferring a binary file in text mode.
  210.  */
  211. int
  212. isbinary (fp)
  213. FILE *fp;
  214. {
  215. int c, i;
  216. int rval;
  217.  
  218.     rval = 0;
  219.     for (i = 0; i < 512; i++) {
  220.         if ((c = getc (fp)) == EOF)
  221.             break;
  222.         if (c & 0x80) {
  223.             /* High bit is set, probably not text */
  224.             rval = 1;
  225.             break;
  226.         }
  227.     }
  228.     /* Assume it was at beginning */
  229.     fseek (fp, 0L, SEEK_SET);
  230.     return rval;
  231. }
  232.  
  233.  
  234. unsigned long
  235. getsize (fp)
  236. FILE *fp;
  237. {
  238.     fseek (fp, 0L, SEEK_END);    /* Go to end of file */
  239.     return (unsigned long) ftell (fp);    /* Return file pointer position */
  240. }
  241.  
  242.  
  243. /* Compute checksum of the first n bytes */
  244. unsigned long
  245. checksum (fp, n)
  246. FILE *fp;
  247. long n;
  248. {
  249. unsigned long sum;
  250. long i;
  251. int c;
  252.  
  253.     rewind (fp);
  254.     sum = 0;
  255.     for (i = 1; i <= n; i++) {
  256.         if ((c = fgetc (fp)) == EOF)
  257.             break;
  258.         sum += (unsigned long) c;
  259.     }
  260.     return sum;
  261. }
  262.  
  263.  
  264. /* Compute MD5 hash of local file */
  265. int
  266. md5hash (fp, hash, ascii)
  267. FILE *fp;
  268. char hash[16];
  269. int ascii;
  270. {
  271. MD5_CTX md;
  272. char *buf;
  273. int len;
  274.  
  275.     MD5Init (&md);
  276.  
  277.     if (ascii) {
  278.         /* Text file, hash canonical form (newlines = crlf) */
  279.         char *cp;
  280.         int c;
  281.  
  282.         cp = buf = mallocw (MD5BLOCK);
  283.         len = 0;
  284.         while ((c = fgetc (fp)) != EOF) {
  285.             if (c == '\n') {
  286.                 *cp++ = '\r';
  287.                 if (++len == MD5BLOCK) {
  288.                     MD5Update (&md, (unsigned char *) buf, (unsigned int) len);
  289.                     kwait (NULL);
  290.                     cp = buf;
  291.                     len = 0;
  292.                 }
  293.             }
  294.             *cp++ = (char) c;
  295.             if (++len == MD5BLOCK) {
  296.                 MD5Update (&md, (unsigned char *) buf, (unsigned int) len);
  297.                 kwait (NULL);
  298.                 cp = buf;
  299.                 len = 0;
  300.             }
  301.         }
  302.         if (len != 0)
  303.             MD5Update (&md, (unsigned char *) buf, (unsigned int) len);
  304.         free (buf);
  305.     } else {
  306.         buf = mallocw (BUFSIZ);
  307.         while ((len = (int) fread (buf, 1, BUFSIZ, fp)) != 0) {
  308.             MD5Update (&md, (unsigned char *) buf, (unsigned int) len);
  309.             kwait (NULL);
  310.         }
  311.         free (buf);
  312.     }
  313.     MD5Final (&md);
  314.     memcpy (hash, md.digest, 16);
  315.     return 0;
  316. }
  317.